﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using ThridLibray;
using MotionCS.Enumerate;
using MotionCS.Helper;
namespace MotionCS.CameraVision
{
    public class DahvisionData : IFrameData
    {
        /// <summary>
        /// 相机序列号
        /// </summary>
        private string serialNo;
        public string SerialNo
        {
            get => serialNo;
            set
            {
                if (value != serialNo)
                {
                    serialNo = value;
                }
            }
        }
        /// <summary>
        /// 相机序列号
        /// </summary>
        private string deviceIp;
        public string DeviceIp
        {
            get => deviceIp;
            set
            {
                if (value != deviceIp)
                {
                    deviceIp = value;
                }
            }
        }
        /// <summary>
        /// 图像数据RAW
        /// </summary>
        private byte[] rawData;
        public byte[] RawData { get => rawData; }
        /// <summary>
        /// 图像数据长度
        /// </summary>
        private int rawLen;
        public int RawLen { get => rawLen; }
        /// <summary>
        /// 图像数据指针
        /// </summary>
        private IntPtr rawPtr;
        public IntPtr RawPtr { get => rawPtr; }
        /// <summary>
        /// 图像宽度
        /// </summary>
        private int nwidth;
        public int Width { get => nwidth; }
        /// <summary>
        /// 图像高度
        /// </summary>
        private int nheight;
        public int Height { get => nheight; }
        /// <summary>
        /// 图片所属工件
        /// </summary>
        private string uuid;
        public string Uuid
        {
            get => uuid;
            set
            {
                if (value != uuid)
                {
                    uuid = value;
                }
            }
        }
        /// <summary>
        /// 图片所属二维码
        /// </summary>
        private string qrcode;
        public string QrCode
        {
            get => qrcode;
            set
            {
                if (value != qrcode)
                {
                    qrcode = value;
                }
            }
        }
        /// <summary>
        /// 图片索引
        /// </summary>
        private int index;
        public int Index
        {
            get => index;
            set
            {
                if (value != index)
                {
                    index = value;
                }
            }
        }
        /// <summary>
        /// 图像帧计数
        /// </summary>
        private uint frameCount;
        public uint FrameCount
        {
            get => frameCount;
            set
            {
                if (value != frameCount)
                {
                    frameCount = value;
                }
            }
        }
        /// <summary>
        /// 采集帧率
        /// </summary>
        private float acqFrameRate;
        public float AcqFrameRate
        {
            get => acqFrameRate;
            set
            {
                if (value != acqFrameRate)
                {
                    AcqFrameRate = value;
                }
            }
        }
        /// <summary>
        /// 相机名称
        /// </summary>
        private string cameraName;
        public string CameraName
        {
            get => cameraName;
            set
            {
                cameraName = value;
            }
        }
        private GrabLightTypeE lightType = GrabLightTypeE.RGBLight;
        /// <summary>
        /// 拍照对应光源
        /// </summary>
        public GrabLightTypeE LightType//-LZC
        {
            get { return lightType; }
            set { lightType = value; }
        }
        /// <summary>
        /// 光机投影下标
        /// </summary>
        private int dlpLocationIndex;
        public int DlpLocationIndex
        {
            get => dlpLocationIndex;
            set => dlpLocationIndex = value;
        }
        /// <summary>
        /// 光机图像下标
        /// </summary>
        private int dlpImageIndex;
        public int DlpImageIndex
        {
            get => dlpImageIndex;
            set => dlpImageIndex = value;
        }
        /// <summary>
        /// 像素格式
        /// </summary>
        public Int32 PixelType;
        /// <summary>
        /// 是否为彩色相机
        /// </summary>
        private bool isColor;
        public bool IsColor
        {
            get => isColor;
            set => isColor = value;
        }

        public int PddingX;
        public int PddingY;
        /// <summary>
        /// 构造函数
        /// </summary>
        public DahvisionData(IntPtr pData, int width, int hight, int len, int pixelType)
        {
            nwidth = width;
            nheight = hight;
            isColor = false;
            PixelType = pixelType;
            rawLen = len;
            rawData = new byte[len];
            rawPtr = Marshal.UnsafeAddrOfPinnedArrayElement(rawData, 0);
            if (pData != IntPtr.Zero)
            {
                Marshal.Copy(pData, rawData, 0, len);
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="width"></param>
        /// <param name="hight"></param>
        /// <param name="color"></param>
        public DahvisionData(int width, int height, bool color)
        {
            nwidth = width;
            nheight = height;
            isColor = color;
            rawLen = color ? 3 * width * height : width * height;
            rawData = new byte[rawLen];
            rawPtr = Marshal.UnsafeAddrOfPinnedArrayElement(rawData, 0);
        }


        /// <summary>
        /// 指针之间进行数据拷贝
        /// </summary>
        /// <param name="pDst">目标地址</param>
        /// <param name="pSrc">源地址</param>
        /// <param name="len">拷贝数据长度</param>
        [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", CharSet = CharSet.Ansi)]
        internal static extern void CopyMemory(IntPtr pDst, IntPtr pSrc, int len);

        /// <summary>
        /// raw转bmp
        /// </summary>
        /// <returns></returns>
        public Bitmap ToBitmap(/*IntPtr pdata, int width, int height, bool isColor*/)
        {
            PixelFormat format = isColor ? PixelFormat.Format24bppRgb : PixelFormat.Format8bppIndexed;
            Bitmap bmp = new Bitmap(nwidth, nheight, format);
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, nwidth, nheight),
                                                    ImageLockMode.WriteOnly, format);

            int imageStride = isColor ? nwidth * 3 : nwidth;
            if (imageStride == bmpData.Stride)
            {
                CopyMemory(bmpData.Scan0, rawPtr, bmpData.Stride * bmp.Height);
            }
            else
            {
                //for (int i = 0; i < bmp.Height; ++i)
                //{
                //    CopyMemory(bmpData.Scan0, pdata, bmpData.Stride * bmp.Height);
                //    Marshal.Copy(imgData, i * imageStride, new IntPtr(bmpData.Scan0.ToInt64() + i * bmpData.Stride), width);
                //}
            }

            bmp.UnlockBits(bmpData);

            if (bmp.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                ColorPalette tempPalette;
                using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
                {
                    tempPalette = tempBmp.Palette;
                }
                for (int i = 0; i < 256; i++)
                {
                    tempPalette.Entries[i] = Color.FromArgb(i, i, i);
                }

                bmp.Palette = tempPalette;
            }

            return bmp;
        }

    }


    public class DahvisionGrab : ICamera
    {
        /// <summary>
        /// 图像信息
        /// </summary>
        private struct ImageInfo
        {
            public uint Width;
            public uint Height;
            public uint PixelType;
        }
        /// <summary>
        /// 日志事件回调
        /// </summary>
        public Action<string> LogoutCallBack { get; set; }
        /// <summary>
        /// 图像事件回调
        /// </summary>
        public Action<IFrameData> ImageCallBack { get; set; }
        /// <summary>
        /// 曝光事件回调
        /// </summary>
        public Action<string> ExposureCallBack { get; set; }
        /// <summary>
        /// 注册图像抓拍结束回调//-LZC
        /// </summary>
        public Action<string> GrabEndCallback { get; set; }
        /// <summary>
        /// 注册帧重拍回调
        /// </summary>
        public Action<string, int> RemakeCallback { get; set; }
        /// <summary>
        /// 图像处理线程
        /// </summary>
        private Thread m_imageHandlerThread = null;
        /// <summary>
        /// 图像处理线程循环标志
        /// </summary>
        private bool m_bHandlerLoop = false;
        /// <summary>
        /// 图像帧队列
        /// </summary>
        private ConcurrentQueue<DahvisionData> m_frameList;
        /// <summary>
        /// 图像信息队列
        /// </summary>
        private ConcurrentQueue<FrameInfo> m_frameInfo;
        /// <summary>
        /// 硬件触发信息
        /// </summary>
        private FrameInfo m_hardTriggerInfo;
        /// 相机设备
        /// </summary>
        private IDevice device;
        /// <summary>
        /// 设备信息
        /// </summary>
        private IDeviceInfo stDevInfo;
        /// <summary>
        /// 连接状态
        /// </summary>
        private bool isConnected;
        /// <summary>
        /// 连接状态
        /// </summary>
        public bool IsConnected 
        {
            get
            {
                if (device == null)
                {
                    return false;
                }
                else
                {
                    return device.IsOpen;
                }
            }
        }
        /// <summary>
        /// 设备信息
        /// </summary>
        public CamInfo Info { get; set; }
        /// <summary>
        /// 图像信息
        /// </summary>
        private ImageInfo m_ImageInfo = new ImageInfo();

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="devInfo"></param>
        public DahvisionGrab()
        {
            m_frameList = new ConcurrentQueue<DahvisionData>();
            m_frameInfo = new ConcurrentQueue<FrameInfo>();
            m_hardTriggerInfo = new FrameInfo();
            m_bHandlerLoop = true;
            m_imageHandlerThread = new Thread(new ThreadStart(ImageHandlerThread));
            m_imageHandlerThread.IsBackground = true;
            m_imageHandlerThread.Start();
        }
        /// <summary>
        /// 搜索设备
        /// </summary>
        /// <param name="DevList"></param>
        public static List<ICamera> SearchDeviceList()
        {
            List<ICamera> cameraList = new List<ICamera>();

            List<IDeviceInfo> devList = Enumerator.EnumerateDevices(DeviceType.DEVICE_TYPE_GIGE | DeviceType.DEVICE_TYPE_U3V);

            for (int i = 0; i < devList.Count; i++)
            {
                CamInfo info = new CamInfo();
                if (devList[i].DeviceTypeEx == DeviceType.DEVICE_TYPE_GIGE)
                {
                    info.strSN = devList[i].SerialNumber;
                    info.strName = devList[i].Name;
                    IGigeDeviceInfo gige = Enumerator.GigeCameraInfo(devList[i].Index);
                    info.strIP = gige.IpAddress;
                    info.strManuf = devList[i].ManufactureInfo;
                    //if (devList[i].Model.Contains("A3"))
                    {
                        cameraList.Add(new DahvisionGrab()
                        {
                            stDevInfo = devList[i],
                            Info = info,
                        });
                    }
                }
                else if (devList[i].DeviceTypeEx == DeviceType.DEVICE_TYPE_U3V)
                {
                    info.strSN = devList[i].SerialNumber;
                    info.strName = devList[i].Name;
                    info.strManuf = devList[i].ManufactureInfo;
                    //if (devList[i].Model.Contains("A3"))
                    {
                        cameraList.Add(new DahvisionGrab()
                        {
                            stDevInfo = devList[i],
                            Info = info,
                        });
                    }
                }
            }

            return cameraList;
        }
        /// <summary>
        /// 查找指定相机
        /// </summary>
        /// <param name="strSn"></param>
        /// <returns></returns>
        public static ICamera FindCameraBySn(string strSn)
        {
            List<IDeviceInfo> devList = Enumerator.EnumerateDevices(DeviceType.DEVICE_TYPE_GIGE);

            for (int i = 0; i < devList.Count; i++)
            {
                CamInfo info = new CamInfo();
                if (devList[i].DeviceTypeEx == DeviceType.DEVICE_TYPE_GIGE)
                {
                    info.strSN = devList[i].SerialNumber;
                    info.strName = devList[i].Name;
                    IGigeDeviceInfo gige = Enumerator.GigeCameraInfo(devList[i].Index);
                    info.strIP = gige.IpAddress;
                    info.strManuf = devList[i].ManufactureInfo;
                    if (/*devList[i].Model.Contains("A3") && */devList[i].SerialNumber.Equals(strSn))
                    {
                        return new DahvisionGrab()
                        {
                            stDevInfo = devList[i],
                            Info = info,
                        };
                    }
                }
                else if (devList[i].DeviceTypeEx == DeviceType.DEVICE_TYPE_U3V)
                {
                    info.strSN = devList[i].SerialNumber;
                    info.strName = devList[i].Name;
                    info.strManuf = devList[i].ManufactureInfo;
                    if (/*devList[i].Model.Contains("A3") && */devList[i].SerialNumber.Equals(strSn))
                    {
                        return new DahvisionGrab()
                        {
                            stDevInfo = devList[i],
                            Info = info,
                        };
                    }
                }
            }

            return null;
        }
        /// <summary>
        /// 打开相机
        /// </summary>
        public bool OpenDevice()
        {
            Enumerator.EnumerateDevices();
            device = Enumerator.GetDeviceByKey(stDevInfo.Key);
            device.CameraOpened += OnCameraOpen;
            device.ConnectionLost += OnConnectLoss;
            device.CameraClosed += OnCameraClose;
            device.MsgChannelArgEvent += OnMsgChannelArgEvent;

            if (!device.Open())
            {
                return false;
            }

            using (IIntegraParameter p = device.ParameterCollection[ParametrizeNameSet.ImageWidth])
            {
                m_ImageInfo.Width = (uint)p.GetValue();
            }
            using (IIntegraParameter p = device.ParameterCollection[ParametrizeNameSet.ImageHeight])
            {
                m_ImageInfo.Height = (uint)p.GetValue();
            }
            using (IEnumParameter p = device.ParameterCollection[ParametrizeNameSet.ImagePixelFormat])
            {
                //string st = p.GetValue();
                m_ImageInfo.PixelType = (uint)GvspPixelFormatType.gvspPixelBayRG8;//(uint)Enum.Parse(typeof(GvspPixelFormatType), st);
            }

            using (IEnumParameter p = device.ParameterCollection[new EnumName("EventSelector")])
            {
                bool bRet = p.SetValue("ExposureEnd");
                ApiCheckHandle("EventSelector", bRet);
            }
            using (IEnumParameter p = device.ParameterCollection[new EnumName("EventNotification")])
            {
                bool bRet = p.SetValue("On");
            }
            device.StreamGrabber.SetBufferCount(8);
            device.StreamGrabber.ImageGrabbed += OnImageGrabbed;

          
            return true;
        }
        /// <summary>
        /// 关闭相机
        /// </summary>
        public void CloseDevice()
        {
            if (device != null)
            {
                m_bHandlerLoop = false;
                device.StreamGrabber.ImageGrabbed -= OnImageGrabbed;
                device.CameraOpened -= OnCameraOpen;
                device.ConnectionLost -= OnConnectLoss;
                device.CameraClosed -= OnCameraClose;
                device.Close();
                device.Dispose();
                device = null;
            }
        }

        /// <summary>
        /// 相机打开回调
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnCameraOpen(object sender, EventArgs e)
        {
            isConnected = true;
        }

        /// <summary>
        /// 相机关闭回调
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnCameraClose(object sender, EventArgs e)
        {
            isConnected = false;
        }

        /// <summary>
        /// 相机丢失回调
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnConnectLoss(object sender, EventArgs e)
        {
            isConnected = false;

            StopGrab();
            CloseDevice();
            Reconnect();
        }
        /// <summary>
        /// 启动抓拍
        /// </summary>
        public void StartGrab()
        {
            if (device != null)
            {
                device.GrabUsingGrabLoopThread();
            }
        }
        /// <summary>
        /// 停止抓拍
        /// </summary>
        public void StopGrab()
        {
            if (device != null)
            {
                device.ShutdownGrab();
            }
        }
        /// <summary>
        /// 设置图像宽度
        /// </summary>
        /// <param name="width"></param>
        public int SetImageWidth(uint width)
        {
            using (IIntegraParameter p = device.ParameterCollection[ParametrizeNameSet.ImageWidth])
            {
                bool bRet = p.SetValue(width);
                ApiCheckHandle("SetImageWidth", bRet);
            }

            return 0;
        }
        /// <summary>
        /// 设置图像高度
        /// </summary>
        /// <param name="height"></param>
        public int SetImageHeight(uint height)
        {
            using (IIntegraParameter p = device.ParameterCollection[ParametrizeNameSet.ImageHeight])
            {
                bool bRet = p.SetValue(height);
                ApiCheckHandle("SetImageHeight", bRet);
            }

            return 0;
        }
        /// <summary>
        /// 设置触发选择器
        /// </summary>
        /// <param name="selector"></param>
        public void SetTriggerSelector(uint selector)
        {
           
        }
        /// <summary>
        /// 设置触发极限
        /// </summary>
        /// <param name="activation">0-上升沿 1-下降沿 2-高电平 3-低电平 4-双边沿</param>
        public void SetTriggerActivation(uint activation)
        {
          
        }
        /// <summary>
        /// 设置触发模式 false-触发关闭(持续)  true-触发打开
        /// </summary>
        /// <param name="mode"></param>
        public void SetTriggerMode(bool mode)
        {
            bool bRet;
            if (device == null)
            {
                return;
            }

            if (mode)
            {
                bRet = device.TriggerSet.Open(TriggerModeEnum.On);

                //using (IEnumParameter p = device.ParameterCollection[ParametrizeNameSet.TriggerMode])
                //{
                //    bRet = p.SetValue(TriggerModeEnum.On);
                //}
            }
            else
            {
                bRet = device.TriggerSet.Open(TriggerModeEnum.Off);
                //using (IEnumParameter p = device.ParameterCollection[ParametrizeNameSet.TriggerMode])
                //{
                //    bRet = p.SetValue(TriggerModeEnum.Off);
                //}
            }
            ApiCheckHandle("SetTriggerMode", bRet);
        }
        /// <summary>
        /// 设置触发源
        /// </summary>
        /// <param name="triggerSource">0-线性0  1-软件</param>
        public void SetTriggerSource(uint triggerSource)
        {
            bool bRet;

            if (device == null)
            {
                return;
            }

            if (triggerSource == 0)
            {
                bRet = device.TriggerSet.Open(TriggerSourceEnum.Line1);
                //using (IEnumParameter p = device.ParameterCollection[ParametrizeNameSet.TriggerSource])
                //{
                //    bRet = p.SetValue(TriggerSourceEnum.Line1);
                //}
            }
            else
            {
                bRet = device.TriggerSet.Open(TriggerSourceEnum.Software);
                //using (IEnumParameter p = device.ParameterCollection[ParametrizeNameSet.TriggerSource])
                //{
                //    bRet = p.SetValue(TriggerSourceEnum.Software);
                //}
            }

            ApiCheckHandle("SetTriggerSource", bRet);
        }
        /// <summary>
        /// 软件触发
        /// </summary>
        public void SoftwareTrigger()
        {
            if (device != null)
            {
                bool bRet = device.ExecuteSoftwareTrigger();
                ApiCheckHandle("SoftwareTrigger", bRet);
            }
        }
        /// <summary>
        /// 设置曝光时间
        /// </summary>
        /// <param name="expTime"></param>
        public void SetExposureTime(float expTime)
        {
            if (device != null)
            {
                using (IEnumParameter p = device.ParameterCollection[ParametrizeNameSet.ExposureAuto])
                {
                    bool bRet = p.SetValue("Auto");
                    ApiCheckHandle("SetExposureAuto", bRet);
                }

                using (IFloatParameter p = device.ParameterCollection[ParametrizeNameSet.ExposureTime])
                {
                    bool bRet = p.SetValue(expTime);
                    ApiCheckHandle("SetExposureTime", bRet);
                }
            }
        }
        /// <summary>
        /// 获取曝光时间
        /// </summary>
        /// <param name="gain"></param>
        public void GetExposureTime(ref float expTime)
        {
            if (device != null)
            {
                using (IFloatParameter p = device.ParameterCollection[ParametrizeNameSet.ExposureTime])
                {
                    expTime = (float)p.GetValue();
                }
            }

            expTime = 0;
        }
        /// <summary>
        /// 设置部分图像输出模式
        /// </summary>
        /// <param name="mode">0-ImagePending 1-PartialImageOutput 
        /// 2-PartialImageDiscard 3-PartialImageFilled</param>
        public void SetPartialImageOutputMode(uint mode)
        {
            
        }
        /// <summary>
        /// 设置线性使能
        /// </summary>
        /// <param name="enable"></param>
        public void SetAbnormalLineEnable(bool enable)
        {
           
        }
        /// <summary>
        /// 设置增益值
        /// </summary>
        /// <param name="gain"></param>
        public void SetGainValue(float gain)
        {
            if (device != null)
            {
                using (IEnumParameter p = device.ParameterCollection[ParametrizeNameSet.GainAuto])
                {
                    bool bRet = p.SetValue("Auto");
                    ApiCheckHandle("SetGainAuto", bRet);
                }

                using (IFloatParameter p = device.ParameterCollection[ParametrizeNameSet.GainRaw])
                {
                    bool bRet = p.SetValue(gain);
                    ApiCheckHandle("SetGain", bRet);
                }
            }
        }
        /// <summary>
        /// 获取增益值
        /// </summary>
        /// <param name="gain"></param>
        public void GetGainValue(ref float gain)
        {
            if (device != null)
            {
                using (IFloatParameter p = device.ParameterCollection[ParametrizeNameSet.GainRaw])
                {
                    gain = (float)p.GetValue();
                }
            }

            gain = 0;
        }
        /// <summary>
        /// 设置硬件触发图片信息
        /// </summary>
        /// <param name="uuid"></param>
        /// <param name="code"></param>
        /// <param name="index"></param>
        /// <param name="total"></param>
        /// <returns></returns>
        public void SetHardTriggerInfo(FrameInfo info)
        {
            m_hardTriggerInfo = info;
        }
        /// <summary>
        /// 清除拍照Info队列 -LZC
        /// </summary>
        public void ClearGrabInfo()
        {
            while (!m_frameInfo.IsEmpty)
            {
                m_frameInfo.TryDequeue(out FrameInfo info);
            }
        }
        /// <summary>
        /// 设置软件触发图片信息
        /// </summary>
        /// <param name="uuid"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public void SoftwareTrigger(string uuid, string code, int index)
        {
            int nRet;

            FrameInfo inf = new FrameInfo();
            inf.uuid = uuid;
            inf.code = code;
            inf.index = index;

            if (index == 0)
            {
                while (!m_frameInfo.IsEmpty)
                {
                    m_frameInfo.TryDequeue(out FrameInfo hik);
                }
            }

            m_frameInfo.Enqueue(inf);

            SoftwareTrigger();
        }
        /// <summary>
        /// 软件触发
        /// </summary>
        public Int32 SoftwareTrigger(FrameInfo info)
        {
            int nRet = 0;

            FrameInfo inf = info;

            if (inf.IsBlackPatch)
            {
                if (m_frameInfo.IsEmpty)
                {
                    DahvisionData frameData = new DahvisionData(IntPtr.Zero, (int)m_ImageInfo.Width, (int)m_ImageInfo.Height,
        (int)(3 * m_ImageInfo.Width * m_ImageInfo.Height), (int)m_ImageInfo.PixelType);

                    frameData.Uuid = inf.uuid;
                    frameData.QrCode = inf.code;
                    frameData.Index = inf.index;
                    frameData.LightType = inf.LightType;

                    m_frameList.Enqueue(frameData);
                }
                else
                {
                    m_frameInfo.Enqueue(inf);
                }

                ExposureCallBack?.Invoke(stDevInfo.SerialNumber);
                GrabEndCallback?.Invoke(stDevInfo.SerialNumber);
            }
            else
            {
                m_frameInfo.Enqueue(inf);
                SoftwareTrigger();
            }

            return nRet;
        }
        /// <summary>
        /// 事件回调函数
        /// </summary>
        /// <param name="pEventInfo"></param>
        /// <param name="pUser"></param>
        private void OnMsgChannelArgEvent(object sender, MsgChannelArgs e)
        {
            if (e.EventID == MsgChannelEvent.MSG_CHANNEL_EVENT_EXPOSURE_END && CameraGrabConfig.GlobalGrabMode == CameraGrabConfig.GrabModelEnum.ExposureEnd)
            {
                ExposureCallBack?.Invoke(stDevInfo.SerialNumber);
            }
        }
        /// <summary>
        /// 图像回调处理
        /// </summary>
        /// <param name="pData"></param>
        /// <param name="pFrameInfo"></param>
        /// <param name="pUser"></param>
        private void OnImageGrabbed(Object sender, GrabbedEventArgs e)
        {
            DahvisionData frame = new DahvisionData(e.GrabResult.Raw, e.GrabResult.Width, e.GrabResult.Height,
                e.GrabResult.ImageSize, (int)e.GrabResult.PixelFmt);
            frame.PddingX = (int)e.GrabResult.ImagePaddingX;
            frame.PddingY = (int)e.GrabResult.ImagePaddingY;
            if (m_frameInfo.Count == 0)
            {
                frame.Uuid = m_hardTriggerInfo.uuid;
                frame.QrCode = m_hardTriggerInfo.code;
                frame.Index = m_hardTriggerInfo.index;
                frame.LightType = m_hardTriggerInfo.LightType;
                frame.DlpLocationIndex = m_hardTriggerInfo.DlpLocationIndex;
                frame.DlpImageIndex = m_hardTriggerInfo.DlpImageIndex++;
              
                GrabEndCallback?.Invoke(stDevInfo.SerialNumber);//-LZC  抓拍结束回调
                if (CameraGrabConfig.GlobalGrabMode == CameraGrabConfig.GrabModelEnum.FrameEnd)
                {
                    ExposureCallBack?.Invoke(stDevInfo.SerialNumber);//新增
                }
                m_frameList.Enqueue(frame);
            }
            else
            {
                FrameInfo inf = new FrameInfo();
                if (m_frameInfo.TryDequeue(out inf))
                {
                    if (inf.IsBlackPatch)
                    {
                        DahvisionData frameData = new DahvisionData(IntPtr.Zero, e.GrabResult.Width, e.GrabResult.Height,
                                e.GrabResult.ImageSize, (int)e.GrabResult.PixelFmt);

                        frameData.Uuid = inf.uuid;
                        frameData.QrCode = inf.code;
                        frameData.Index = inf.index;
                        frameData.LightType = inf.LightType;
                        ApiCheckHandle("黑图？？？", false);
                        m_frameList.Enqueue(frameData);
                    }
                    else
                    {
                        frame.Uuid = inf.uuid;
                        frame.QrCode = inf.code;
                        frame.Index = inf.index;
                        frame.LightType = inf.LightType;
                     
                        GrabEndCallback?.Invoke(stDevInfo.SerialNumber);//-LZC  抓拍结束回调                             
                        if (CameraGrabConfig.GlobalGrabMode == CameraGrabConfig.GrabModelEnum.FrameEnd)
                        {
                            ExposureCallBack?.Invoke(stDevInfo.SerialNumber);//新增
                        }
                        m_frameList.Enqueue(frame);
                    }
                }
            }
        }

        private bool IsMonoPixelFormat(GvspPixelFormatType enType)
        {
            switch (enType)
            {
                case GvspPixelFormatType.gvspPixelMono10:
                case GvspPixelFormatType.gvspPixelMono10Packed:
                case GvspPixelFormatType.gvspPixelMono12:
                case GvspPixelFormatType.gvspPixelMono12Packed:
                    return true;
                default:
                    return false;
            }
        }

        private bool IsColorPixelFormat(GvspPixelFormatType enType)
        {
            switch (enType)
            {
                case GvspPixelFormatType.gvspPixelRGB8:
                //case GvspPixelFormatType.gvspPixelBGR8:
                case GvspPixelFormatType.gvspPixelYUV422_8_UYVY:
                case GvspPixelFormatType.gvspPixelYUV422_8:
                case GvspPixelFormatType.gvspPixelBayGR8:
                case GvspPixelFormatType.gvspPixelBayRG8:
                case GvspPixelFormatType.gvspPixelBayGB8:
                case GvspPixelFormatType.gvspPixelBayBG8:
                case GvspPixelFormatType.gvspPixelBayGB10:
                case GvspPixelFormatType.gvspPixelBayGB10Packed:
                case GvspPixelFormatType.gvspPixelBayBG10:
                case GvspPixelFormatType.gvspPixelBayBG10Packed:
                case GvspPixelFormatType.gvspPixelBayRG10:
                case GvspPixelFormatType.gvspPixelBayRG10Packed:
                case GvspPixelFormatType.gvspPixelBayGR10:
                case GvspPixelFormatType.gvspPixelBayGR10Packed:
                case GvspPixelFormatType.gvspPixelBayGB12:
                case GvspPixelFormatType.gvspPixelBayGB12Packed:
                case GvspPixelFormatType.gvspPixelBayBG12:
                case GvspPixelFormatType.gvspPixelBayBG12Packed:
                case GvspPixelFormatType.gvspPixelBayRG12:
                case GvspPixelFormatType.gvspPixelBayRG12Packed:
                case GvspPixelFormatType.gvspPixelBayGR12:
                case GvspPixelFormatType.gvspPixelBayGR12Packed:
                    return true;
                default:
                    return false;
            }
        }
        /// <summary>
        /// 图像处理线程
        /// </summary>
        private void ImageHandlerThread()
        {
            try
            {
                while (m_bHandlerLoop)
                {
                    if (m_frameList.IsEmpty)
                    {
                        ThreadHelper.Delay(2);
                        continue;
                    }

                    m_frameList.TryDequeue(out DahvisionData frame);
                    GvspPixelFormatType DstPixelType = GvspPixelFormatType.pixelTypeUndefined;
                    bool frameColor = false;
                    if (IsColorPixelFormat((GvspPixelFormatType)frame.PixelType))
                    {
                        DstPixelType = GvspPixelFormatType.gvspPixelBGR8;
                        frameColor = true;
                    }
                    else if (IsMonoPixelFormat((GvspPixelFormatType)frame.PixelType))
                    {
                        DstPixelType = GvspPixelFormatType.gvspPixelMono8;
                        frameColor = false;
                    }
                    else if ((GvspPixelFormatType)frame.PixelType == GvspPixelFormatType.gvspPixelBGR8)
                    {
                        frame.IsColor = true;
                    }
                    if (frame.QrCode == null) frame.QrCode = "";
                    if (DstPixelType != GvspPixelFormatType.pixelTypeUndefined)
                    {
                        DahvisionData frameData = new DahvisionData(frame.Width, frame.Height, frameColor);
                        frameData.Uuid = frame.Uuid;
                        frameData.QrCode = frame.QrCode;
                        frameData.Index = frame.Index;
                        frameData.LightType = frame.LightType;
                        frameData.DlpLocationIndex = frame.DlpLocationIndex;
                        frameData.DlpImageIndex = frame.DlpImageIndex;
                        frameData.SerialNo = stDevInfo.SerialNumber;
                        frameData.DeviceIp = Enumerator.GigeCameraInfo(stDevInfo.Index).IpAddress;
                        frameData.CameraName = stDevInfo.Name;
                        if (DstPixelType == GvspPixelFormatType.gvspPixelBGR8)
                        {
                            RGBFactory.ToRGB(frame.RawPtr, frame.RawLen, frame.Width, frame.Height, frameColor, (GvspPixelFormatType)frame.PixelType, frameData.RawPtr, frameData.RawLen);
                        }
                        else
                        {
                            RGBFactory.ToMono8(frame.RawPtr, frame.RawLen, frame.Width, frame.Height, frame.PddingX, frame.PddingY, (GvspPixelFormatType)frame.PixelType, frameData.RawPtr, frameData.RawLen);
                        }
                        Logout($"{frameData.SerialNo},收到到图像.");
                        ImageCallBack?.Invoke(frameData);
                    }
                    else
                    {
                        frame.SerialNo = stDevInfo.SerialNumber;
                        frame.DeviceIp = Enumerator.GigeCameraInfo(stDevInfo.Index).IpAddress;
                        frame.CameraName = stDevInfo.Name;
                        //Logout($"{Info.strName}:{Info.strSN},收到到图像.");
                        ImageCallBack?.Invoke(frame);
                    }
                }
            }
            catch (Exception ex)
            {
                Logout($"{ex}");
            }
        }

        /// <summary>
        /// 重连相机
        /// </summary>
        private void Reconnect()
        {
            while (true)
            {
                if (OpenDevice())
                {
                    //SetTriggerMode(m_triggerMode);
                    //SetTriggerSource(m_triggerSource);
                    StartGrab();
                    Logout(stDevInfo.SerialNumber + "相机重连成功.");
                    break;
                }
                ThreadHelper.Delay(2000);
            }
        }
        /// <summary>
        /// 释放设备
        /// </summary>
        public void Dispose()
        {
            m_bHandlerLoop = false;
            //m_imageHandlerThread.Abort();
            StopGrab();
            CloseDevice();
            Logout("释放相机.");
        }
        /// <summary>
        /// 相机API异常日志
        /// </summary>
        /// <param name="api"></param>
        /// <param name="nRet"></param>
        private void ApiCheckHandle(string api, bool bRet)
        {
            if (!bRet)
            {
                Logout(api + " Failed,SN:" + stDevInfo.SerialNumber);
            }
        }
        /// <summary>
        /// 日志输出
        /// </summary>
        /// <param name="logtxt"></param>
        private void Logout(string logtxt)
        {
            LogoutCallBack?.Invoke($"{Info.strName}:{logtxt}");
        }
    }
}
